package com.joven.shelltest.utils.pdf;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.joven.shelltest.annotation.BoldFont;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Objects;

/**
 * PDF表格处理
 *
 * @Author wzj
 * @Date 2023-08-24 08:41
 **/
public class PdfTableBuilder extends PdfBase {

    /**
     * 表格列数
     */
    private int colSize;

    /**
     * 表格
     */
    private PdfPTable table;

    /**
     * 构造类
     *
     * @return com.ah.ums.service.pdf.PdfTableBuilder
     */
    public static PdfTableBuilder builder(int colSize) {
        return new PdfTableBuilder(colSize);
    }

    /**
     * 无边框table
     * @param colSize 列数
     * @param totalSize 宽带
     * @return PdfTableBuilder
     */
    public static PdfTableBuilder specialBuilder(int colSize, Integer totalSize) {
        return new PdfTableBuilder(colSize, totalSize);
    }

    public static PdfTableBuilder builder(int colSize, int totalWidth, float[] widths) throws DocumentException {
        return new PdfTableBuilder(colSize, totalWidth, widths);
    }

    /**
     * 构造类
     *
     * @return com.ah.ums.service.pdf.PdfTableBuilder
     */
    public static PdfTableBuilder builder(Class clazz) {
        return new PdfTableBuilder(clazz);
    }

    /**
     * 构造函数
     */
    private PdfTableBuilder(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        int size = 0;
        for (Field field : fields) {
            if ("serialVersionUID".equals(field.getName())) {
                continue;
            }
            size++;
        }
        this.colSize = size;
        table = new PdfPTable(colSize);
    }

    /**
     * 构造函数，默认纸张A4
     */
    private PdfTableBuilder(int colSize) {
        this.colSize = colSize;
        table = new PdfPTable(colSize);
    }

    private PdfTableBuilder(int colSize, int totalWidth, float[] widths) throws DocumentException {
        this.colSize = colSize;
        table = new PdfPTable(colSize);
//        table.setHorizontalAlignment(0);
        table.setTotalWidth(totalWidth);
        table.setLockedWidth(true);
        table.setWidths(widths);
    }

    private PdfTableBuilder(int colSize, Integer totalSize) {
        this.colSize = colSize;
        table = new PdfPTable(colSize);
        // 设置表格宽度比例为%100
        table.setWidthPercentage(100);
        // 设置宽度:宽度平均
        table.setTotalWidth(totalSize);
        // 锁住宽度
        table.setLockedWidth(true);
        // 设置表格上面空白宽度
        table.setSpacingBefore(10f);
        // 设置表格下面空白宽度
        table.setSpacingAfter(10f);
        table.getDefaultCell().setBorder(0);
        table.getDefaultCell().setBorderColor(BaseColor.WHITE);
        table.setPaddingTop(50);
        table.setSplitLate(false);
    }

    public PdfPTable build() {
        return table;
    }

    public PdfTableBuilder titleRow(Collection<String> titles) {
        titleRow(PdfCellBuilder.builder().borderColor(BaseColor.BLACK).bgColor(BaseColor.LIGHT_GRAY).build(),
                PdfFontBuilder.builder().fontStyle(Font.BOLD).build(),
                titles);
        return this;
    }

    public PdfTableBuilder titleRow(Font font, Collection<String> titles) {
        titleRow(PdfCellBuilder.builder().borderColor(BaseColor.BLACK).bgColor(BaseColor.LIGHT_GRAY).build(),
                font,
                titles);
        return this;
    }

    public PdfTableBuilder titleRow(PdfPCell cell, Collection<String> titles) {
        titleRow(cell, PdfFontBuilder.builder().fontStyle(Font.BOLD).build(), titles);
        return this;
    }

    public PdfTableBuilder titleRow(PdfPCell cell, Font font, Collection<String> titles) {
        // 根据列数和属性数量，决定处理个数
        int size = Math.min(colSize, titles.size());
        int handleCount = 0;
        Iterator<String> iterator = titles.iterator();
        while (iterator.hasNext()) {
            if (handleCount >= size) {
                break;
            }
            String title = iterator.next();
            title = StrUtil.isNotEmpty(title) ? title : "";
            table.addCell(titleCell(cell, font, title));
            handleCount++;
        }
        table.completeRow();
        return this;
    }

    /**
     * @param clazz 必须包含 @ExcelProperty注解
     * @return com.ah.ums.service.pdf.PdfTableBuilder
     */
    public PdfTableBuilder titleRow(Class clazz) {
        titleRow(PdfCellBuilder.builder().borderColor(BaseColor.BLACK).bgColor(BaseColor.LIGHT_GRAY).build(),
                PdfFontBuilder.builder().fontStyle(Font.BOLD).build(),
                clazz);
        return this;
    }

    public PdfTableBuilder titleRow(Font font, Class clazz) {
        titleRow(PdfCellBuilder.builder().borderColor(BaseColor.BLACK).bgColor(BaseColor.LIGHT_GRAY).build(), font, clazz);
        return this;
    }

    public PdfTableBuilder titleRow(PdfPCell cell, Class clazz) {
        titleRow(cell, PdfFontBuilder.builder().fontStyle(Font.BOLD).build(), clazz);
        return this;
    }

    public PdfTableBuilder titleRow(PdfPCell cell, Font font, Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            if ("serialVersionUID".equals(field.getName())) {
                continue;
            }
            ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
            String data = ObjectUtil.isNotEmpty(annotation) ? annotation.value()[0] : field.getName();
            table.addCell(titleCell(cell, font, data));
        }
        table.completeRow();
        return this;
    }

    public PdfTableBuilder row(Collection<String> list) {
        row(PdfCellBuilder.builder().build(), PdfFontBuilder.builder().build(), list);
        return this;
    }

    public PdfTableBuilder row(Font font, Collection<String> list) {
        row(PdfCellBuilder.builder().build(), font, list);
        return this;
    }

    public PdfTableBuilder row(PdfPCell cell, Collection<String> list) {
        row(cell, PdfFontBuilder.builder().build(), list);
        return this;
    }

    public PdfTableBuilder row(PdfPCell cell, Font font, Collection<String> list) {
        // 根据列数和属性数量，决定处理个数
        int size = Math.min(colSize, list.size());

        int handleCount = 0;
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            if (handleCount >= size) {
                break;
            }
            String title = iterator.next();
            title = StrUtil.isNotEmpty(title) ? title : "";
            table.addCell(cell(cell, font, title));
            handleCount++;
        }
        table.completeRow();
        return this;
    }

    public <T> PdfTableBuilder row(T obj) throws IllegalAccessException {
        row(PdfCellBuilder.builder().build(), PdfFontBuilder.builder().build(), obj);
        return this;
    }

    public <T> PdfTableBuilder row(Font font, T obj) throws IllegalAccessException {
        row(PdfCellBuilder.builder().build(), font, obj);
        return this;
    }

    public <T> PdfTableBuilder row(PdfPCell cell, T obj) throws IllegalAccessException {
        row(cell, PdfFontBuilder.builder().build(), obj);
        return this;
    }

    public <T> PdfTableBuilder row(PdfPCell cell, Font font, T obj) throws IllegalAccessException {
        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        // 根据列数和属性数量，决定处理个数
        for (Field field : fields) {
            if ("serialVersionUID".equals(field.getName())) {
                continue;
            }
            field.setAccessible(true);
            Object f = field.get(obj);
            DateTimeFormat annotation = field.getAnnotation(DateTimeFormat.class);
            String data;
            if (ObjectUtil.isNotEmpty(annotation)) {
                String format = annotation.value();
                if (f instanceof Date) {
                    data = DateUtil.format((Date) f, format);
                } else if (f instanceof LocalDateTime) {
                    data = DateUtil.format((LocalDateTime) f, format);
                } else {
                    data = "";
                }
            } else {
                data = ObjectUtil.isNotEmpty(f) ? f.toString() : "";
            }
            data = StrUtil.isNotEmpty(data) ? data : "";
            BoldFont boldFont = field.getAnnotation(BoldFont.class);
            if (ObjectUtil.isNotEmpty(boldFont)) {
                int bold = boldFont.isBold() ? Font.BOLD : Font.NORMAL;
                table.addCell(cell(cell, new Font(BASE_FONT, boldFont.fontSize(), bold, BaseColor.BLACK), data, boldFont.horizontal()));
            } else {
                table.addCell(cell(cell, font, data));
            }

        }
        table.completeRow();
        return this;
    }

    /**
     * 获取单元格
     *
     * @param cell 单元格
     * @param font 字体
     * @param text 内容
     * @return com.itextpdf.text.pdf.PdfPCell
     */
    private PdfPCell titleCell(PdfPCell cell, Font font, String text) {
        cell.setPhrase(new Phrase(text, font));
        return cell;
    }

    /**
     * 获取单元格
     *
     * @param cell pdf单元格
     * @param font 字体
     * @param text 内容
     * @return com.itextpdf.text.pdf.PdfPCell
     */
    private PdfPCell cell(PdfPCell cell, Font font, String text) {
        cell.setPhrase(new Phrase(text, font));
        return cell;
    }

    /**
     * @param cell       pdf单元格
     * @param font       字体
     * @param text       内容
     * @param horizontal 水平居中对齐方式
     * @return PdfPCell
     */
    private PdfPCell cell(PdfPCell cell, Font font, String text, int horizontal) {
        cell.setPhrase(new Phrase(text, font));
        cell.setHorizontalAlignment(horizontal);
        return cell;
    }

    public static class PdfCellBuilder {
        /**
         * 单元格 padding大小
         */
        private Float padding = CELL_PADDING;

        /**
         * 单元格 水平位置
         * <pre>
         *     Element.ALIGN_LEFT       (0) 居左
         *     Element.ALIGN_CENTER     (1) 居中
         *     Element.ALIGN_RIGHT      (2) 居右
         *     Element.ALIGN_JUSTIFIED  (3) 自适应
         * </pre>
         */
        private Integer horizontalAlign = Element.ALIGN_CENTER;
        /** 单元格 垂直位置：Element.ALIGN_TOP-居上，Element.ALIGN_MIDDLE-居中，Element.ALIGN_BOTTOM-居下 */

        /**
         * 单元格 垂直位置
         * <pre>
         *     Element.ALIGN_TOP         (4) 居上
         *     Element.ALIGN_MIDDLE      (5) 居中
         *     Element.ALIGN_BOTTOM      (6) 居下
         * </pre>
         */
        private Integer verticalAlign = Element.ALIGN_MIDDLE;

        /**
         * 单元格 边框颜色
         */
        private BaseColor borderColor;

        /**
         * 单元格 字体颜色
         */
        private BaseColor bgColor;

        /**
         * 构造类
         */
        public static PdfCellBuilder builder() {
            return new PdfCellBuilder();
        }

        /**
         * 构造函数，默认纸张A4
         */
        private PdfCellBuilder() {
        }

        public PdfCellBuilder padding(float padding) {
            this.padding = padding;
            return this;
        }

        public PdfCellBuilder horizontalAlign(Integer horizontalAlign) {
            this.horizontalAlign = horizontalAlign;
            return this;
        }

        public PdfCellBuilder verticalAlign(Integer verticalAlign) {
            this.verticalAlign = verticalAlign;
            return this;
        }

        public PdfCellBuilder borderColor(BaseColor borderColor) {
            this.borderColor = borderColor;
            return this;
        }

        public PdfCellBuilder bgColor(BaseColor bgColor) {
            this.bgColor = bgColor;
            return this;
        }

        /**
         * 构造函数，默认纸张A4
         */
        public PdfPCell build() {
            // 创建单元格
            PdfPCell cell = new PdfPCell();
            // 表格padding
            cell.setPadding(padding);
            // 设置单元格的水平居中
            cell.setHorizontalAlignment(horizontalAlign);
            // 设置单元格的垂直居中
            cell.setVerticalAlignment(verticalAlign);
            cell.setBorderColor(borderColor);
            cell.setBackgroundColor(bgColor);
            return cell;
        }

        public PdfPCell build(Integer horizontalAlign, Integer verticalAlign) {
            // 创建单元格
            PdfPCell cell = new PdfPCell();
            // 表格padding
            cell.setPadding(padding);
            // 设置单元格的水平居中
            cell.setHorizontalAlignment(Objects.nonNull(horizontalAlign) ? horizontalAlign : Element.ALIGN_CENTER);
            // 设置单元格的垂直居中
            cell.setVerticalAlignment(Objects.nonNull(verticalAlign) ? verticalAlign : Element.ALIGN_MIDDLE);
            cell.setBorderColor(borderColor);
            cell.setBackgroundColor(bgColor);
            return cell;
        }


        public PdfPCell buildSpecial() {
            // 创建单元格
            PdfPCell cell = new PdfPCell();
            // 表格padding
            cell.setPadding(padding);
            // 设置单元格的水平居中
            cell.setHorizontalAlignment(Element.ALIGN_LEFT);
            // 设置单元格的垂直居中
            cell.setVerticalAlignment(verticalAlign);
            cell.setBorder(0);
            cell.setBorderColor(BaseColor.WHITE);
            cell.setBackgroundColor(bgColor);
            return cell;
        }

        public PdfPCell buildSpecial(Integer horizontalAlign, Integer verticalAlign) {
            // 创建单元格
            PdfPCell cell = new PdfPCell();
            // 表格padding
            cell.setPadding(padding);
            // 设置单元格的水平居中
            cell.setHorizontalAlignment(Objects.nonNull(horizontalAlign) ? horizontalAlign : Element.ALIGN_CENTER);
            // 设置单元格的垂直居中
            cell.setVerticalAlignment(Objects.nonNull(verticalAlign) ? verticalAlign : Element.ALIGN_MIDDLE);
            cell.setBorder(0);
            cell.setBorderColor(BaseColor.WHITE);
            cell.setBackgroundColor(bgColor);
            return cell;
        }
    }

}
